using UnityEngine;
using System.Collections;

//人物状态机
[RequireComponent(typeof(CharacterController), typeof(AIFollow))]
public class Person : AIUnit
{
    //主要状态属性
    private bool isMoving = false;//移动
    private bool isDied = false;//死亡(不可逆)
    private bool isLoaded = false;//被挂接
    private bool isLoading = false;//挂接
    private bool isLieDowned = false;//倒下(不可逆)
	private bool isMask = false;//是否带有面罩

    private Person loadedPerson;//挂接的父对象
    private Person loadingPerson;//挂接的人

    //关键属性
    public float speed = 0.0f;//当前速度
    public float rotationSpeed = 2.5F;//当前转弯速度
    public float life;//生命值
    public float liedownlife;//倒下的生命值

    private string currentAnimation = "root";//当前动画
    private string lastAnimation = "root";//上次动画
	
	private void Start()
	{
		//this.StartCoroutine(Idle());
		Physics.IgnoreLayerCollision(9, 9);
	}
	
	private IEnumerator Idle()
	{
		while(true)
		{
			int r = Random.Range(0,2);
			if(currentAnimation == "root" && r==1)
			{
				r = Random.Range(0,2);
				if(r==0)
					SetAnimation("idle1");
				else
					SetAnimation("idle2");
				float s = Random.Range(3, 10);
				yield return new WaitForSeconds(s);
				if(currentAnimation == "idle1" || currentAnimation == "idle2")
					SetAnimation("root");
			}
			float sec = Random.Range(10, 20);
			yield return new WaitForSeconds(sec);
		}
	}

    //设置动画(重载)
    public override void SetAnimation(string ani)
    {
        if (ani != null && ani != "")
            currentAnimation = ani;
        if (lastAnimation != currentAnimation)
        {
            animation.CrossFade(currentAnimation);
            lastAnimation = currentAnimation;
            SyncState();
        }
    }

    //停止移动
    public override void Stop()
    {
		if(isMoving)
		{
	        isMoving = false;
	        speed = 0;
	        SetAnimation("root");
		}
    }

    //向前移动，边走边转身
    public override void MoveTowards(Vector3 position)
    {
        Vector3 direction = position - transform.position;
        direction.y = 0;

        /*if (direction.magnitude < 0.2F)
        {
            Stop();
            return;
        }*/

        // 插值与目标的转角
		Quaternion q = Quaternion.LookRotation(direction);
        transform.rotation = q;//Quaternion.Slerp(transform.rotation, q, rotationSpeed * Time.deltaTime);
        //？？
        transform.eulerAngles = new Vector3(0, transform.eulerAngles.y, 0);

        // 获取本地坐标下的向前方向
        Vector3 forward = transform.TransformDirection(Vector3.forward);
        //向前方向和当前位置与目标位置的向量的点积（夹角越小点积越大），这样NPC拐弯的时候速度就慢些
        float speedModifier = Vector3.Dot(forward, direction.normalized);
        speedModifier = Mathf.Clamp01(speedModifier);

        //计算实际偏移的向量
        direction = forward * speed * speedModifier;
        //移动一小步
        this.GetComponent<CharacterController>().SimpleMove(direction);
		if(direction.magnitude>0)
			this.SendMessage("SyncTransform", SendMessageOptions.DontRequireReceiver);
    }

    //同步状态
    private void SyncState()
    {
    }

    //移动到目标（一般是从UnitManager发过来）
    public void MoveToPoint(Vector3 targetPos)
    {
        //死了或者倒下或者被挂接不能切换到移动状态
        if (isDied || isLieDowned || isLoaded) return;
        //由于移动状态可以和isloading状态叠加，所以只需取消技能(如果有)状态就可以了
        //if (isSkilling)
        //    CancelSkill();

        continousTargetSearch = false;
        this.targetPos = targetPos;
        SendMessage("AIMoveToPoint", targetPos);

        isMoving = true;
        if (isLoading)
        {
            SetAnimation("walk");
            speed = 1.5f;
        }
        else
        {
            SetAnimation("run");
            speed = 3.0f;
        }
        SyncState();
    }

    //跟踪目标
    public void FollowTarget(Transform target)
    {
        //死了或者倒下或者被挂接不能切换到移动状态
        if (isDied || isLieDowned || isLoaded) return;
        //由于移动状态可以和isloading状态叠加，所以只需取消技能状态就可以了
        //if (isSkilling)
        //    CancelSkill();

        continousTargetSearch = true;
        this.targetPos = target.position;
        this.targetObject = target;

        isMoving = true;
        if (isLoading)
        {
            SetAnimation("run_loaded");
            speed = 1.5f;
        }
        else
        {
            SetAnimation("run");
            speed = 3.0f;
        }
        SyncState();
    }

    //迁移到根状态
    public void Root()
    {
        //死了或者倒下或者被挂接不能切换到根状态
        if (isDied || isLieDowned || isLoaded) return;
         //取消当前技能
        if (isMoving)
            Stop();
        if (isLoading)
            Unload();
        if (isSkilling)
            CancelSkill();

        SetAnimation("root");
        SyncState();
    }

    //迁移到死亡状态
    public void Die()
    {
        Root();
        isDied = true;
        SetAnimation("die");
        life = 0;
        SyncState();
    }

    //迁移到倒下状态
    public void LieDown()
    {
        Root();
        isLieDowned = true;
        SetAnimation("liedown");
        SyncState();
    }

    //迁移到挂接状态
    public void Load(Person person)
    {
        //死了或者倒下不能切换到挂接状态
        if (isDied || isLieDowned) return;
        Root();
        isLoading = true;
        this.loadingPerson = person;
        SetAnimation("root_loaded");
        SyncState();
    }

    private void Unload()
    {
        //取消挂接
        this.loadingPerson = null;
        isLoading = false;
        SetAnimation("root");
        SyncState();
    }

    //迁移到被挂接状态
    public void Beload(Person person)
    {
        //未死或者未倒下不能切换到被挂接状态
        if (!isDied || !isLieDowned) return;
        Root();
        isLoaded = true;
        this.loadedPerson = person;
        SetAnimation("beload");
        SyncState();
    }

    //这个方法只能由技能调用（不可主动逆转）
    private void Unbeload()
    {
        //取消被挂接
        this.transform.parent = null;

        this.loadedPerson = null;
        isLoaded = false;
        SetAnimation("liedown");
        SyncState();
    }

    //迁移到被执行技能状态（持续技能）
    public override void ExecuteSkill(BaseSkill skill)
    {
        //死了或者倒下或者被挂接或者挂接不能切换到被挂接状态
        //在挂接状态下，如果技能可以叠加，那么技能是可以执行的
        if (isDied || isLieDowned || isLoaded || isLoading) return;
        Root();
        //技能执行会导致切换到挂接和被挂接的状态(比如背负技能)
        isSkilling = true;
        this.currentSkill = skill;
        skill.Execute();
        SyncState();
    }
	
	public void ExecuteNewSkill(string skill)
	{
		BaseSkill sk = (BaseSkill)this.GetComponent(skill);
		if(sk != null)
		{
			ExecuteSkill(sk);
		}
	}

    //技能执行完成
    public override void OnSkillFinish(BaseSkill skill)
    {
        currentSkill = null;
        isSkilling = false;
        SetAnimation("root");
        //通知Choise执行完成
        if (SkillInitiator != null)
        {
            SkillInitiator.SendMessage("OnSkillFinish", skill);
            SkillInitiator = null;
        }
    }

    //取消当前执行技能
    private void CancelSkill()
    {
        if (this.currentSkill != null)
        {
            this.currentSkill.Cancel();
            this.currentSkill = null;
        }
        isSkilling = false;
        SetAnimation("root");
        SyncState();
    }

    //受到伤害
    public void Damage(float value)
    {
        life -= value;
        if (life < 0.001)
            Die();
        else if (life < liedownlife)
            LieDown();
		SyncState();
    }
	
	public void FaceTo(Transform go)
	{
		Vector3 v = go.position - this.transform.position;
		v.y = 0;
		this.transform.forward = v;
		this.SendMessage("SyncTransform", SendMessageOptions.DontRequireReceiver);
	}
	
	public void FaceToFace(Transform go)
	{
		this.transform.forward = -go.forward;
		this.SendMessage("SyncTransform", SendMessageOptions.DontRequireReceiver);
	}
	
	public void FaceLike(Transform go)
	{
		this.transform.forward = go.forward;
		this.SendMessage("SyncTransform", SendMessageOptions.DontRequireReceiver);
	}
	
	public void Mask(bool m)
	{
		isMask = m;
		Renderer[] rs = this.transform.GetComponentsInChildren<Renderer>();
		foreach(Renderer r in rs)
			r.enabled = m;
		SyncState();
	}
}
